package com.doophan.dac.bridge.socket;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * Socket Server
 * @author Vincent Wu
 * @date 2021-04-01
 */
@Component
@Slf4j
public class SocketServerRunner implements CommandLineRunner {
    public static ServerSocket server;
    private static ConcurrentHashMap<Socket, Integer> sockets;
    @Value("${socket.threadnum}")
    private int SOCKET_NUM;
    private static final int FREE_FLAG = 0;
    private static final int BUSY_FLAG = 1;
    @Value("${socket.port}")
    private Integer socketPort;

    @Override
    public void run(String... args) throws Exception {
        server = new ServerSocket(socketPort);
        log.info("==============socket server启动==============");
        // 阻塞
        initSockets();
        Socket socket = getFreeSocket();
        while(true) {
            // 断开重连
            // 每秒发心跳
            DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
            try {
                dos.writeUTF("t");
                dos.flush();
//                log.info("==============发送心跳==============");
            } catch (SocketException e) {
                log.info("==============断开重连==============");
                initSockets();
                socket = getFreeSocket();
            }
            TimeUnit.SECONDS.sleep(1);
        }
    }

    /**
     * 创建指定数目的socket连接
     * @throws IOException
     */
    private void initSockets() throws IOException {
        sockets = new ConcurrentHashMap<>(10);
        for (int i = 0; i < SOCKET_NUM; i++) {
            Socket socket = server.accept();
            // 0-空闲 1-忙碌
            sockets.put(socket, 0);
        }
        log.info("==============成功创建"+SOCKET_NUM+"个socket连接==============");
    }

    /**
     * 获取一个空闲的socket
     * @return
     */
    public static Socket getFreeSocket() {
        Socket res = null;
        boolean loop = true;
        // 循环直至取到空闲的Socket
        while(loop) {
            for (Map.Entry<Socket, Integer> entry : sockets.entrySet()) {
                if (entry.getValue() == FREE_FLAG) {
                    entry.setValue(BUSY_FLAG);
                    res = entry.getKey();
                    loop = false;
                    break;
                }
            }
        }
        return res;
    }

    /**
     * 释放socket
     * 这里想到了切面处理
     * @param socket
     */
    public static void releaseSocket(Socket socket) {
        for(Map.Entry<Socket, Integer> entry : sockets.entrySet()) {
            if(entry.getKey().equals(socket)) {
                entry.setValue(FREE_FLAG);
            }
        }
    }
}
